/*
 * Copyright 2009 Google Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.appengine.demos.oauth;

import com.google.appengine.api.urlfetch.HTTPRequest;

import java.io.IOException;
import java.net.URL;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Fetches portable contacts via OAuth.
 */
public class ContactsFetcher {
  
  private static final String CONTACTS_URL =
      "http://www-opensocial.googleusercontent.com/api/people/@me/@all?fields=displayName,emails";
  
  private static final String REQUEST_TOKEN_URL =
      "https://www.google.com/accounts/OAuthGetRequestToken?" +
      "scope=http://www-opensocial.googleusercontent.com/api/people/";
  
  private static final String APPROVAL_URL = "https://www.google.com/accounts/OAuthAuthorizeToken";
  
  private static final String ACCESS_TOKEN_URL =
      "https://www.google.com/accounts/OAuthGetAccessToken";
  
  private static final String STATE_COOKIE = "contacts_state";
 
  private static final String MY_CALLBACK = "http://gaeoauthjava.appspot.com/sign/poco/callback";

  private final OAuthFetchService fetcher = new OAuthFetchService();

  /**
   * Fetches the current user's contacts.
   * 
   * @param req http request that triggered this fetch
   * @param resp http response to send
   * @param receivedCallback pass the current URL if this is an OAuth callback, or null otherwise.
   */
  public OAuthFetchResponse fetchContacts(HttpServletRequest req, HttpServletResponse resp,
      String receivedCallback) throws IOException {
    OAuthFetchOptions options = new OAuthFetchOptions();
    options.setOAuthDesiredCallbackUrl(MY_CALLBACK);
    options.setOAuthReceivedCallbackUrl(receivedCallback);
    options.setOAuthRequestTokenUrl(REQUEST_TOKEN_URL);
    options.setOAuthAccessTokenUrl(ACCESS_TOKEN_URL);
    options.setOAuthAuthorizationUrl(APPROVAL_URL);
    options.setOAuthState(getStateCookie(req));
    options.setOAuthServiceName("google");
    options.setOAuthTokenName("contacts");
    options.setOAuthUseToken("always");
    
    HTTPRequest fetchRequest = new HTTPRequest(new URL(CONTACTS_URL));
    OAuthFetchResponse fetchResponse = fetcher.fetch(fetchRequest, options);
    if (fetchResponse.getOAuthState() != null) {
      // Track transient state associated with the OAuth approval process.
      setStateCookie(resp, fetchResponse.getOAuthState());
    }
    return fetchResponse;
  }

  private String getStateCookie(HttpServletRequest req) {
    Cookie[] cookies = req.getCookies();
    if (cookies == null) {
      return null;
    }
    for (Cookie cookie : cookies) {
      if (cookie.getName().equals(STATE_COOKIE)) {
        return cookie.getValue();
      }
    }
    return null;
  }
  
  private void setStateCookie(HttpServletResponse resp, String state) {
    Cookie stateCookie = new Cookie(STATE_COOKIE, state);
    stateCookie.setPath("/sign/poco");
    resp.addCookie(stateCookie);
  }
}
